package com.hjx.movie.core.security.service.impl;

import com.hjx.movie.core.security.mapper.AuthMapper;
import com.hjx.movie.core.security.model.AuthUser;
import com.hjx.movie.core.security.service.IAuthService;
import com.hjx.movie.core.system.service.admin.impl.*;
import com.hjx.movie.persistence.system.model.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>Title:</p>
 * <p>Description:</p>
 *
 * @author hjx
 * @date 2021/1/4 - 0:10
 */
@Slf4j
@Service
@CacheConfig(cacheNames = "IvyMovie:SpringCache:AuthCache",keyGenerator = "cacheKeyGenerator")
public class AuthService implements IAuthService {
    @Resource
    private AuthMapper authMapper;
    @Resource
    RedisTemplate<String,Object> redisTemplate;

    @Override
    public String findUserIdByLoginType(String username, Integer loginType) {
        return authMapper.findUserIdByLoginType(username,loginType);
    }

    @Override
    public String findUserId(String username) {
        return authMapper.findUserId(username);
    }

    @Cacheable(unless="#result == null")
    @Override
    public AuthUser findUserById(String uid) {
        return authMapper.findUserById(uid);
    }

//    @Cacheable(unless="#result == null")
    @Override
    public List<String> findRoleByUserId(Long uid) {
        List<Long> collect = findRoleIdByUserId(uid);
        HashOperations<String, String, IvyRole> hashOperations = redisTemplate.opsForHash();
        List<String> roleCodes = new ArrayList<>();
        collect.forEach(id->{
            String roleCode = Objects.requireNonNull(hashOperations.get(RoleService.ROLE_CACHE_DATA, id.toString())).getRoleCode();
            roleCodes.add(roleCode);
        });
        return roleCodes;

//        return hashOperations.values(RoleService.ROLE_CACHE_DATA).stream()
//                .filter(item->collect.contains(item.getRoleId()))
//                .map(IvyRole::getRoleCode)
//                .collect(Collectors.toList());
//        return authMapper.findRoleByUserId(uid);
    }

    @Cacheable(unless="#result == null")
    @Override
    public List<String> findAuthByRoleCode(List<String> roles) {
        return authMapper.findAuthByRoleCode(roles);
    }

//    @Cacheable(unless="#result == null")
    @Override
    public List<Long> findRoleIdByUserId(Long uid) {
        // 用户ID查询出角色ID 角色状态必须为启用
        HashOperations<String, String, IvyUserRole> userRoleHashOperations = redisTemplate.opsForHash();
        HashOperations<String, String, IvyRole> roleHashOperations = redisTemplate.opsForHash();
        return  userRoleHashOperations.values(UserRoleService.USER_ROLE_CACHE_DATA).stream()
                .filter(item ->{
                    //判断当前UserRole的userId与入参的一不一致 并且判断状态
                    if(item.getUserId().equals(uid)&& item.getStatus()){
                        //如果一致 从缓存中再获取对应的角色 继续判断状态 根据状态决定
                        IvyRole ivyRole = roleHashOperations.get(RoleService.ROLE_CACHE_DATA, item.getRoleId().toString());
                        assert ivyRole != null;
                        return ivyRole.getStatus();
                    }
                    return false;
                })
                .map(IvyUserRole::getRoleId)
                .collect(Collectors.toList());


    }
//    @Cacheable(unless="#result == null")
    @Override
    public List<String> findAuthByRoleId(List<Long> roles) {
        //根据角色ID在角色权限中间表查询出 接口ID 状态必须为启用
        HashOperations<String, String, IvyRoleApi> hashOperations = redisTemplate.opsForHash();
        Set<Long> apiIds =  hashOperations.values(RoleApiService.ROLE_API_CACHE_DATA).stream()
                .filter(item->roles.contains(item.getRoleId())&& item.getStatus())
                .map(IvyRoleApi::getApiId).collect(Collectors.toSet());
        //接口ID查询接口路径 状态必须为启用
        HashOperations<String, String, IvyApi> hashOperations2 = redisTemplate.opsForHash();
        Set<String> apis = hashOperations2.values(ApiService.API_CACHE_DATA)
                .stream().filter(item->apiIds.contains(item.getApiId())&& item.getStatus())
                .map(IvyApi::getApiUrl).collect(Collectors.toSet());
        return apis.isEmpty()? Collections.emptyList():new ArrayList<>(apis);
    }

    @Cacheable(unless="#result == null")
    @Override
    public List<String> findAuthByUserId(Long uid) {
        return authMapper.findAuthByUserId(uid);
    }
    // 根据角色查询可访问的菜单
    @Override
    public List<IvyMenu> findMenuByRoleId(List<Long> roleIds) {
        HashOperations<String, String, IvyRoleMenu> hashOperations = redisTemplate.opsForHash();
        HashOperations<String, String, IvyMenu> hashOperations2 = redisTemplate.opsForHash();

        Set<Long> menuIds = hashOperations.values(RoleMenuService.ROLE_MENU_CACHE_DATA).stream()
                .filter(item -> roleIds.contains(item.getRoleId())&&item.getStatus())
                .map(IvyRoleMenu::getMenuId).collect(Collectors.toSet());

        return hashOperations2.values(MenuService.MENU_CACHE_DATA).stream()
                .filter(item->menuIds.contains(item.getMenuId())&& item.getStatus())
                .collect(Collectors.toList());
    }
}
